package net.butov.wrappers;

import net.sf.cglib.proxy.Callback;
import net.sf.cglib.proxy.Enhancer;

import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;

/**
 * @author Maxim Butov
 * @version $Id$
 */
public class EnhancerObjectFactory<T> {

    public static <T> EnhancerObjectFactory<T> getInstance(Class<T> superClass, Callback callback) {
        return getInstance(superClass, null, callback);
    }

    private static final Class[] EMPTY_CLASS_ARRAY = new Class[0];

    public static <T> EnhancerObjectFactory<T> getInstance(Class<T> superClass, Class sourceClass, Callback callback) {
        return new EnhancerObjectFactory<T>(superClass, sourceClass == null ? EMPTY_CLASS_ARRAY : sourceClass.getInterfaces(),
                callback);
    }

    private Enhancer enhancer = new Enhancer();

    private EnhancerObjectFactory(Class<T> superClass, Class[] interfaces, Callback callback) {

        enhancer.setSuperclass(superClass);

        Set<Class> allInterfaces = new HashSet<Class>();
        allInterfaces.addAll(Arrays.asList(interfaces));
        allInterfaces.addAll(Arrays.asList(superClass.getInterfaces()));
        enhancer.setInterfaces(allInterfaces.toArray(new Class[allInterfaces.size()]));

        enhancer.setCallback(callback);
    }

    public T newInstance() {
        return (T) enhancer.create();
    }

    public T newInstance(Class[] argumentTypes, Object[] arguments) {
        return (T) enhancer.create(argumentTypes, arguments);
    }
}
